package com.online.web.signature;

import com.online.web.domain.IntelligentCallParameters;

import java.lang.reflect.Field;
import java.security.MessageDigest;
import java.util.*;

/**
 * 生成sign
 *
 * @author xiangtianlei
 * @date 2023/08/10
 */
public class SignUtils {

    private static final String CHARSET = "UTF-8";
    private static final String SIGN_TYPE = "MD5";

    public static void main(String[] args) {
        // 请求参数
        Map<String, String> params = new HashMap<>();
        params.put("action", "equity");
        params.put("appId", "1");
        params.put("timestamp", "1629352706");
        String privateKey = "2514d8a41c7bf5583ea570047a2836d2";
        // 生成签名
        String signature = generateSignature(params, privateKey);
        System.out.println("Signature：：： " + signature);
    }

    /**
     * 转换为智能调用参数
     *
     * @param parameters 参数
     * @return {@link Map}<{@link String}, {@link String}>
     */
    public static Map<String, String> convertToIntelligentCallParameters(IntelligentCallParameters parameters) {
        return getStringStringMap(parameters);
    }

    public static Map<String, String> getStringStringMap(IntelligentCallParameters parameters) {
        Map<String, String> paramMap = new HashMap<>();
        Class<?> clazz = parameters.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            try {
                Object value = field.get(parameters);
                if (value != null) {
                    paramMap.put(field.getName(), value.toString());
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return paramMap;
    }

    /**
     * 生成签名
     *
     * @param params     参数个数
     * @param privateKey 私钥
     * @return {@link String}
     */
    public static String generateSignature(Map<String, String> params, String privateKey) {
        // 将参数按照参数名的ASCII码从小到大排序
        List<Map.Entry<String, String>> sortedParams = new ArrayList<>(params.entrySet());
        sortedParams.sort(Comparator.comparing(Map.Entry::getKey));
        // 拼接参数字符串
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> entry : sortedParams) {
            if (!"sign".equals(entry.getKey())) {
                sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
        }
        sb.append("key=").append(privateKey);
        System.out.println("连接参数：" + sb.toString());
        // 计算MD5摘要并转换为大写字符串
        return MD5(sb.toString());
    }

    /**
     * 生成 MD5
     *
     * @param data 待处理数据
     * @return MD5结果
     */
    public static String MD5(String data) {
        try {
            MessageDigest md = MessageDigest.getInstance(SIGN_TYPE);
            byte[] array = md.digest(data.getBytes(CHARSET));
            StringBuilder sb = new StringBuilder();
            for (byte item : array) {
                sb.append(Integer.toHexString((item & 0xFF) |
                        0x100), 1, 3);
            }
            return sb.toString().toUpperCase();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


}
